package com.jic.product.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import com.jic.common.base.vo.RestResult;
import com.jic.product.constant.consist.ResponseCode;
import com.jic.product.entity.Product;
import com.jic.product.exception.AppRuntimeException;
import com.jic.product.mapper.*;
import com.jic.product.model.entity.*;
import com.jic.product.model.entity.MStore;
import com.jic.product.service.MStoreBalanceService;
import com.jic.product.service.MStoreOperateProductInfoService;
import com.jic.product.store.request.*;
import com.jic.product.service.MStoreManageService;
import com.jic.product.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * 接口实现类
 *
 * @author : 建投数据科技(山东)有限公司
 * @version : v1.0.0
 * @email :
 * @since : 2020-03-09 10:12:20
 */
@Service
@Slf4j
public class MStoreManageServiceImpl implements MStoreManageService {

    @Resource
    private MStoreMapper mapper;

    @Resource
    private MStoreBalanceMapper mStoreBalanceMapper;

    @Resource
    private MStoreOperateLogMapper mStoreOperateLogMapper;

    @Resource
    private MStoreManageMapper mStoreManageMapper;

    @Resource
    private MStoreVirtualBalanceMapper mStoreVirtualBalanceMapper;
    @Resource
    private MStoreVirtualShopRelMapper mStoreVirtualShopRelMapper;

    @Autowired
    private ProductService productService;

    @Autowired
    private MStoreBalanceService mStoreBalanceService;

    @Resource
    private MStoreOperateProductInfoService mStoreOperateProductInfoService;

    /**
     * 冻结台账
     * 下单:店铺冻结,虚拟仓冻结;
     * 发货:下单提交时,门店仓提交,虚拟仓提交,实体仓提交;
     *
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<Boolean> frozen(MStoreFrozenRequest request) {
        boolean flagFrozen = verifyFrozen(request);
        if (!flagFrozen) {
            log.error("【库存冻结】冻结所需参数校验未通过");
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }
        //根据productId 获取该商品的库存明细;
        Long productId = request.getProductId();
        Product product = new Product();
        product.setId(productId);
        product.setDeleteFlag(0);
        Product productInfo = productService.queryByPrimaryKey(productId);
        if (productInfo == null) {
            log.info("【库存冻结】商品信息不存在或者不唯一,产品编号:" + productId);
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }

        /**
         * 操作的仓库的维度
         * 1:店铺;
         * 2:虚拟仓;
         * 3:实体仓;
         * 12:是店铺和虚拟仓;
         * 123:是店铺,虚拟仓;
         */
        //1.获取门店仓信息
        Long shopId = request.getShopId();
        MStore mStore = new MStore();
        mStore.setDeptId(shopId);// TODO  门店信息为部门编码;
        mStore.setType(2);//1-实体仓;2-门店仓;
        mStore.setDeleteFlag(0);
        List<MStore> mStoreList = mapper.selectBySelective(mStore);
        if (mStoreList == null || mStoreList.size() != 1) {
            log.info("【库存冻结】根据店铺Id查询实体仓库信息不存在或不唯一");
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }

        MStoreBalance balance = new MStoreBalance();
        balance.setProductId(request.getProductId());
        balance.setStoreId(mStoreList.get(0).getId());
        balance.setDeleteFlag(0);
        List<MStoreBalance> mStoreBalances = mStoreBalanceMapper.selectBySelective(balance);
        if (mStoreBalances == null || mStoreBalances.size() != 1) {
            log.info("【库存冻结】根据产品Id,店铺对应的台账表不存在");
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }

        MStoreBalance balanceUpdate = mStoreBalances.get(0);
        Long total = balanceUpdate.getTotal();
        Long available = balanceUpdate.getAvailable();
        Long block = balanceUpdate.getBlock();
        Long applyNum = request.getApplyNum();

        if (available == null || available < applyNum) {
            log.info("【库存冻结】门店仓实际库存小于请求冻结量");
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }

        MStoreOperateLog mStoreOperate = new MStoreOperateLog();
        mStoreOperate.setBalanceId(balanceUpdate.getId());
        mStoreOperate.setApplyNum(applyNum);
        mStoreOperate.setActualNum(applyNum);
        mStoreOperate.setOrderId(request.getOrderId());
        /**
         * 下单后,库存冻结,整个出库动作未完成;0-待处理;
         * 发货时,产品出库,再更新状态为已完成;1-已完成;
         */
        mStoreOperate.setStatus(0);
        mStoreOperate.setProductId(productId);
        /**
         * 1-实体台账表;2-虚拟台账表;
         */
        mStoreOperate.setType(1);
        if (request.isFrozenFlag()) {
            mStoreOperate.setOperateId(0L);
            mStoreOperate.setOperateDesc("订单冻结库存,冻结门店仓台账");
            balanceUpdate.setAvailable(available - applyNum);
            balanceUpdate.setBlock(block + applyNum);
        } else {
            log.info("开始直接出库");
            mStoreOperate.setOperateId(0L);
            mStoreOperate.setOperateDesc("订单增减库存,增减冻结门店仓台账");
            balanceUpdate.setTotal(total - applyNum);
            balanceUpdate.setAvailable(available - applyNum);
            balanceUpdate.setTotal(total - applyNum);

        }
        int insert = mStoreOperateLogMapper.insertSelective(mStoreOperate);
        if (insert != 1) {
            log.error("【库存出入】虚拟库-虚拟库冻结台账失败!orderId:" + (request.getOrderId() == null ? "订单Id为空" : request.getOrderId()));
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }

        int i = mStoreBalanceMapper.updateByPrimaryKey(balanceUpdate);
        if (i != 1) {
            log.error("【库存冻结】更新门店仓台账表失败!");
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }

        MStoreVirtualShopRel mStoreVirtualShopRel = new MStoreVirtualShopRel();
        mStoreVirtualShopRel.setShopId(shopId);
        mStoreVirtualShopRel.setDeleteFlag(0);
        List<MStoreVirtualShopRel> mStoreVirtualShopRels = mStoreVirtualShopRelMapper.selectBySelective(mStoreVirtualShopRel);
        if (mStoreVirtualShopRels.size() != 1) {
            log.error("【库存出入】根据店铺Id,查询到虚拟仓和门店仓关联表记录不唯一,无法操作");
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }

        mStoreVirtualShopRel = mStoreVirtualShopRels.get(0);

        MStoreVirtualBalance mStoreVirtualBalance = new MStoreVirtualBalance();
        mStoreVirtualBalance.setProductId(request.getProductId());
        mStoreVirtualBalance.setStoreId(mStoreVirtualShopRel.getVitualId());//TODO  需要分仓服务获取;
        List<MStoreVirtualBalance> mStoreVirtualBalances = mStoreVirtualBalanceMapper.selectBySelective(mStoreVirtualBalance);
        if (mStoreVirtualBalances.size() != 1) {
            log.error("【库存出入】根据操作编号,查询到虚拟仓台账记录不唯一,无法操作");
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }

        MStoreOperateLog mStoreOperate2 = new MStoreOperateLog();
        mStoreOperate2.setBalanceId(balanceUpdate.getId());
        mStoreOperate2.setApplyNum(applyNum);
        mStoreOperate2.setActualNum(applyNum);
        mStoreOperate2.setOrderId(request.getOrderId());
        mStoreOperate2.setOperateId(0L);
        mStoreOperate2.setOperateDesc("订单冻结库存,冻结虚拟仓台账");
        mStoreOperate2.setProductId(productId);
        /**
         * 1-实体台账表;2-虚拟台账表;
         */
        mStoreOperate2.setType(1);
        int insert1 = mStoreOperateLogMapper.insert(mStoreOperate2);
        if (insert1 != 1) {
            log.error("【库存出入】虚拟库-虚拟库冻结台账失败!orderId:" + (request.getOrderId() == null ? "订单Id为空" : request.getOrderId()));
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }

        MStoreVirtualBalance mStoreVirtualBalanceUpdate = mStoreVirtualBalances.get(0);

        Long available1 = mStoreVirtualBalanceUpdate.getAvailable();
        Long block1 = mStoreVirtualBalanceUpdate.getBlock();

        mStoreVirtualBalanceUpdate.setAvailable(available1 - applyNum);
        mStoreVirtualBalanceUpdate.setBlock(block1 + applyNum);
        int i1 = mStoreVirtualBalanceMapper.updateByPrimaryKey(mStoreVirtualBalanceUpdate);
        if (i1 != 1) {
            log.error("【库存出入】虚拟库-虚拟库冻结台账失败!balanceId:" + (mStoreVirtualBalanceUpdate.getId() == null ? "没有获取到台账表中的订单号" : mStoreVirtualBalanceUpdate.getId()));
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }
        return RestResult.success(true);
    }


    /**
     * 根据 productId 获取所有包含该产品的实体类仓库列表
     *
     * @param mStoreSubmitRequest 请求参数
     * @return 返回参数;
     */


    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult<Boolean> submit(MStoreSubmitRequest mStoreSubmitRequest) {
        //常规校验
        boolean flag = verifySubmit(mStoreSubmitRequest);
        if (!flag) {
            log.error("【库存出入】基本校验未通过");
            throw new AppRuntimeException(ResponseCode.EXCEPTION);
        }
        Long orderId = mStoreSubmitRequest.getOrderId();
        MStoreOperateLog mStoreOperate = new MStoreOperateLog();
        mStoreOperate.setOrderId(orderId);
        /**
         * 状态为0表示订单未完成;
         */
        mStoreOperate.setStatus(0);
        mStoreOperate.setDeleteFlag(0);
        List<MStoreOperateLog> mStoreOperates = mStoreOperateLogMapper.selectBySelective(mStoreOperate);
        for (MStoreOperateLog mo : mStoreOperates) {
            Long actualNum = mo.getActualNum();
            if (mo.getType() == 1) {
                MStoreBalance balance = new MStoreBalance();
                balance.setProductId(mStoreSubmitRequest.getProductId());
                balance.setId(mo.getBalanceId());
                balance.setDeleteFlag(0);
                List<MStoreBalance> mStoreBalances = mStoreBalanceMapper.selectBySelective(balance);
                if (mStoreBalances.size() != 1) {
                    log.error("【库存出入】根据操作编号,查询到台账记录不唯一,无法操作");
                    throw new AppRuntimeException(ResponseCode.EXCEPTION);
                }
                MStoreBalance mStoreBalance = mStoreBalances.get(0);
                Long total = mStoreBalance.getTotal();
                Long block = mStoreBalance.getBlock();
                if (block < actualNum) {
                    log.info("【库存出入】被冻结数小于解冻申请数目,无法操作!");
                    throw new AppRuntimeException(ResponseCode.EXCEPTION);
                }
                mStoreBalance.setTotal(total - actualNum);
                mStoreBalance.setBlock(block - actualNum);
                int i = mStoreBalanceMapper.updateByPrimaryKey(mStoreBalance);
                if (i != 1) {
                    log.error("【库存出入】操作失败!balanceId:" + (mStoreBalance.getId() == null ? "没有获取到台账表中的订单号" : mStoreBalance.getId()));
                    throw new AppRuntimeException(ResponseCode.EXCEPTION);
                }
            } else if (mo.getType() == 2) {
                //修改虚拟仓台账;
                MStoreVirtualBalance mStoreVirtualBalance = new MStoreVirtualBalance();
                mStoreVirtualBalance.setProductId(mStoreSubmitRequest.getProductId());
                mStoreVirtualBalance.setStoreId(mStoreSubmitRequest.getStoreId());//TODO  需要分仓服务获取;
                List<MStoreVirtualBalance> mStoreVirtualBalances = mStoreVirtualBalanceMapper.selectBySelective(mStoreVirtualBalance);
                if (mStoreVirtualBalances.size() != 1) {
                    log.error("【库存出入】根据操作编号,查询到虚拟仓台账记录不唯一,无法操作");
                    throw new AppRuntimeException(ResponseCode.EXCEPTION);
                }

                MStoreVirtualBalance mStoreVirtualBalanceUpdate = mStoreVirtualBalances.get(0);

                Long total1 = mStoreVirtualBalanceUpdate.getTotal();
                Long block1 = mStoreVirtualBalanceUpdate.getBlock();

                mStoreVirtualBalanceUpdate.setTotal(total1 - actualNum);
                mStoreVirtualBalanceUpdate.setBlock(block1 - actualNum);
                int i1 = mStoreVirtualBalanceMapper.updateByPrimaryKey(mStoreVirtualBalanceUpdate);
                if (i1 != 1) {
                    log.error("【库存出入】虚拟库-虚拟库修改台账失败!balanceId:" + (mStoreVirtualBalanceUpdate.getId() == null ? "没有获取到台账表中的订单号" : mStoreVirtualBalanceUpdate.getId()));
                    throw new AppRuntimeException(ResponseCode.EXCEPTION);
                }

            }
            //TODO 根据productId ,调取路由分仓服务,获取实体类仓库;
            //修改实体仓台账
            MStoreBalance mStoreBalance1 = new MStoreBalance();
            mStoreBalance1.setStoreId(mStoreSubmitRequest.getStoreId());//TODO  需要由分仓路由告诉我,从哪个仓库出货;
            List<MStoreBalance> mStoreBalancesList = mStoreBalanceMapper.selectBySelective(mStoreBalance1);
            if (mStoreBalancesList.size() != 1) {
                log.error("【库存出入】实体库台账表-根据实体仓编号,查询到虚拟仓台账记录不唯一,无法操作");
                throw new AppRuntimeException(ResponseCode.EXCEPTION);
            }
            mStoreBalance1 = mStoreBalancesList.get(0);
            Long total2 = mStoreBalance1.getTotal();
            Long available2 = mStoreBalance1.getAvailable();
            Long block2 = mStoreBalance1.getBlock();

            mStoreBalance1.setTotal(total2 - actualNum);
            mStoreBalance1.setAvailable(available2 - actualNum);
            int i2 = mStoreBalanceMapper.updateByPrimaryKey(mStoreBalance1);
            if (i2 != 1) {
                log.error("【库存出入】实体库-虚拟库修改台账失败!balanceId:" + (mStoreBalance1.getId() == null ? "没有获取到台账表中的订单号" : mStoreBalance1.getId()));
                throw new AppRuntimeException(ResponseCode.EXCEPTION);
            }

        }
        return RestResult.success(true);
    }


    /**
     * 根据订单信息,查询实体仓信息
     *
     * @param request 含有产品编号的查询实体类
     * @return
     */
    @Override
    public List<MStore> listMStoreInfoByOrderInfo(MStoreQueryRequest request) {
        List<MStore> storeList = mStoreManageMapper.listMStoreInfoByOrderInfo(request);
        return storeList;
    }

    /**
     * 获取可售数量最多的实体仓列表;
     *
     * @param request 请求参数
     * @return MStoreResponse 响应参数
     * author taozhouchuan
     * @date 2020-4-28 20:14:23
     */
    @Override
    public MStore listMStoreOfMaxAvailable(MStoreQueryRequest request) {
        List<MStoreReq> mStoreList = request.getMStoreList();
        if (mStoreList != null && mStoreList.size() > 0) {
            return mStoreManageMapper.listMStoreOfMaxAvailable(mStoreList);
        } else {
            return new MStore();
        }
    }


    /**
     * 获取当天发货量最少的的实体仓列表;
     *
     * @param request 请求参数
     * @return MStoreResponse 响应参数
     * author taozhouchuan
     * @date 2020-4-28 20:14:23
     */
    @Override
    public MStore listStoreOfMinDelivery(MStoreQueryRequest request) {
        List<MStoreReq> mStoreList = request.getMStoreList();
        if (mStoreList != null && mStoreList.size() > 0) {
            return mStoreManageMapper.listStoreOfMinDelivery(mStoreList);
        } else {
            return new MStore();
        }
    }

    /**
     * 撤销操作
     *
     * @param mStoreRecallRequest 请求撤销的操作;
     * @return
     */
    @Override
    public boolean recall(MStoreRecallRequest mStoreRecallRequest) {
        return false;
    }


    /**
     * 校验业务数据完整性;
     *
     * @param mStoreRecallRequest
     * @return
     */
    @Override
    public boolean validateBusinessCompleteness(MStoreRecallRequest mStoreRecallRequest) {
        return false;
    }

    /**
     * 同步实体库存
     *
     * @param request
     * @return
     */
    @Override
    public Boolean syncStock(MStoreShopSyncStockRequest request) {
        String storeCode = request.getStoreCode();
        String productCode = request.getProductCode();
        MStoreBalance balance = null;
        MStore mStore = null;
        //查询对应实体仓信息
        MStore store = new MStore();
        store.setCode(request.getStoreCode());
        List<MStore> stores = mapper.selectBySelective(store);
        if (CollectionUtil.isNotEmpty(stores)) {
            mStore = stores.get(0);
        } else {
            //todo 无对应实体仓后续操作
            return false;
        }
        //1.根据仓库id和商品编码查询是否存在台账
        MStoreBalance queryBalance = new MStoreBalance();
        queryBalance.setProductCode(productCode);
        queryBalance.setStoreId(mStore.getId());
        List<MStoreBalance> balances = mStoreBalanceMapper.selectBySelective(queryBalance);
        if (CollectionUtil.isNotEmpty(balances)) {
            //操作台账
            balance = balances.get(0);
            //商家收货为添加库存 直接操作  m_store_operate_product_info对应商品记录  和 m_store_balance对应台账
            balance.setAvailable(balance.getAvailable() + request.getRealRecievedNum());
            int balanceFlag = mStoreBalanceService.saveOrUpdate(balance);
            //保存operate_product_info记录
            MStoreOperateProductlog mStoreOperateProductlog = new MStoreOperateProductlog();
            BeanUtils.copyProperties(request, mStoreOperateProductlog);
            mStoreOperateProductlog.setOperateId(null);
            mStoreOperateProductlog.setBalanceId(balance.getId());
            mStoreOperateProductlog.setActualNum(Long.valueOf(request.getRealRecievedNum()));
            //todo 查询商品id
            mStoreOperateProductlog.setProductId(1L);
            mStoreOperateProductlog.setApplyNum(Long.valueOf(request.getRealRecievedNum()));
            int operateFlag = mStoreOperateProductInfoService.save(mStoreOperateProductlog);

            if (balanceFlag == 1 && operateFlag == 1) {
                return true;
            }

        } else {
            //新增此商品台账记录
            balance = new MStoreBalance();
            balance.setStoreId(stores.get(0).getId());
            balance.setTotal(Long.valueOf(request.getRealRecievedNum()));
            balance.setAvailable(Long.valueOf(request.getRealRecievedNum()));
            balance.setBlock(0L);
            balance.setProductCode(productCode);
            balance.setDeleteFlag(0);
            balance.setCreateTime(new Date());
            balance.setUpdateTime(new Date());
            mStoreBalanceService.saveOrUpdate(balance);


        }


        return true;
    }

    /**
     * 根据商家code得到实体仓信息
     *
     * @param request
     * @return
     */
    @Override
    public com.jic.product.store.request.MStore getStoreByMerchantCode(MStoreReq request) {
        com.jic.product.store.request.MStore result = null;

        MStore store = new MStore();
        List<MStore> stores = mapper.selectBySelective(store);
        if (CollectionUtil.isEmpty(stores)) {
            //根据商家code新增一个Mstore
            MStore mstore = new MStore();
            mstore.setName("商家店铺");
            mstore.setType(1);
            mstore.setStatus(1);
            mstore.setDeleteFlag(0);
            mstore.setCode(RandomUtil.randomUUID());
            mstore.setStoreCode(RandomUtil.randomString(10));
            mapper.insert(mstore);
            result = new com.jic.product.store.request.MStore();
            BeanUtils.copyProperties(mstore, result);

        } else {
            result = new com.jic.product.store.request.MStore();
            BeanUtils.copyProperties(stores.get(0), result);
            return result;
        }
        return result;
    }


    /**
     * 校验订单提交请求参数
     *
     * @param mStoreSubmitRequest 含有产品Id 的订单提交请求参数;
     * @return 订单提交响应参数;
     */
    private boolean verifySubmit(MStoreSubmitRequest mStoreSubmitRequest) {
        if (null == mStoreSubmitRequest.getProductId() || 0 == mStoreSubmitRequest.getProductId()) {
            log.info("产品Id,无法继续操作");
            return false;
        }
        if (null == mStoreSubmitRequest.getOrderId() || 0 == mStoreSubmitRequest.getOrderId()) {
            log.info("订单Id为空,无法继续操作");
            return false;
        }
        if (null == mStoreSubmitRequest.getStoreId() || 0 == mStoreSubmitRequest.getStoreId()) {
            log.info("仓库Id为空,无法继续操作");
            return false;
        }
        return true;
    }


    /**
     * 库存冻结前参数校验
     *
     * @param request 冻结库存请求参数
     * @return 冻结库存响应结果
     * @auther: taozhouchuan
     * @Date 2020-4-27 21:42:15
     */
    private boolean verifyFrozen(MStoreFrozenRequest request) {
        if (null == request.getProductId() || 0 == request.getProductId()) {
            log.info("产品Id,无法继续操作");
            return false;
        }
        if (null == request.getShopId() || 0 == request.getShopId()) {
            log.info("产品Id,无法继续操作");
            return false;
        }
        if (null == request.getOrderId() || 0 == request.getOrderId()) {
            log.info("订单Id,无法继续操作");
            return false;
        }
        if (null == request.getApplyNum() || 0 == request.getApplyNum()) {
            log.info("申请数量,无法继续操作");
            return false;
        }
        return true;
    }


}
